import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:kq_flutter_core_widget/widgets/tabBar/kq_extended_tab_bar_view.dart';
import 'package:kq_flutter_core_widget/widgets/tabBar/kq_tabs.dart';

import 'kq_tab_bar.dart';

/// KqPadTabBar + KqPabTabBarView 组合控件
///
/// @author 周卓
///
class KqPadTabBarPageView extends StatefulWidget {
  /// 指示器
  final PadIndicatorType indicatorType;

  /// 指示器大小
  final TabBarIndicatorSize? indicatorSize;

  /// 文字颜色和下划线颜色处理器，下划线颜色跟随选中的文字颜色，如果不设置，默认使用[_KqTabBarState._defaultTextColorBuilder]
  final Color? Function(
          PadIndicatorType indicatorType, bool selected, Color defColor)?
      textColorBuilder;

  /// 文字颜色和下划线颜色处理器，下划线颜色跟随选中的文字颜色，如果不设置，默认使用[_KqTabBarState._defaultUnderlineColorBuilder]
  final Color? Function(PadIndicatorType indicatorType, Color defColor)?
      underlineColorBuilder;

  /// Tab数据
  final List<PadTabDataEntity> tabs;

  /// tabBar 背景颜色
  final Color? tabBarBackgroundColor;

  /// pageView 背景颜色
  final Color? pageBackgroundColor;

  /// 右侧抽屉，在TabBar下方
  final Widget? endDrawer;

  /// 用于控制抽屉开关
  final GlobalKey<ScaffoldState>? drawerGlobalKey;

  /// 自定义TabBar右侧控件，比如管理Tab的菜单
  final Widget? customTabRightView;

  /// 自定义TabBar和KqPageView之间的自定义控件，比如搜素框
  final Widget? customTabBottomView;

  /// 页面
  final List<Widget> pages;

  /// TabBar是否可左右滚动，默认false
  final bool tabScrollable;

  /// KqPageView是否可左右滑动，默认true
  final bool pageScrollable;

  /// 默认页面下标，支持动态修改
  final int initialPageIndex;

  /// KqPageView是否根据子View高度自动调整高度
  final bool pageViewAutoHeight;

  /// 页面改变回调
  final Function(int index, PadTabDataEntity entity)? onPageChanged;

  /// 这个是用来刷新控件用的，比如某个条件触发后需要改变控件的高度，大多数清空下用不到
  final KqPadTabBarPageViewController? controller;

  /// 当 Scrollable 滚动未停止的时候，是默认阻止其内容获得 hittest， 这就会导致在快速切换 tab 的时候， 给人一种不能马上操作内容的感觉
  /// 将 ShouldIgnorePointerWhenScrolling 设置成false，这样的话 Scrollable 在滚动中也不会阻止内容获得 hittest。
  final bool shouldIgnorePointerWhenScrolling;

  /// 是否关联父类滑动，此值为true时，当自身不可滑动时，会将滑动事件传递给父类
  final bool link;

  /// 底部分割线颜色
  final Color? dividerColor;

  /// TabBar左右两边间距，默认0
  final double tabBarHorizontalMargin;

  /// 指示器左右padding;TabBarIndicatorSize最好设置成tab
  final double? indicatorHorizontalPadding;

  /// 指示器下自定义widget
  final Widget? customView;

  /// 是否隐藏底部分割线
  final bool hideDivider;

  /// 字体大小处理器，如果不设置，默认使用[_KqPadTabBarState._defaultFontSizeBuilder]
  final double Function(PadIndicatorType indicatorType, bool selected)?
      fontSizeBuilder;

  /// 字体加粗处理器，如果不设置，默认使用[_KqPadTabBarState._defaultFontSizeBuilder]
  final FontWeight Function(PadIndicatorType indicatorType, bool selected)?
      fontWeightBuilder;
  const KqPadTabBarPageView(
      {super.key,
      required this.tabs,
      required this.pages,
      this.endDrawer,
      this.tabBarBackgroundColor,
      this.pageBackgroundColor,
      this.textColorBuilder,
      this.underlineColorBuilder,
      this.drawerGlobalKey,
      this.customTabRightView,
      this.customTabBottomView,
      this.pageViewAutoHeight = false,
      this.indicatorType = PadIndicatorType.underline,
      this.indicatorSize,
      this.controller,
      this.tabBarHorizontalMargin = 0,
      this.tabScrollable = false,
      this.pageScrollable = true,
      this.initialPageIndex = 0,
      this.onPageChanged,
      this.dividerColor,
      this.shouldIgnorePointerWhenScrolling = true,
      this.indicatorHorizontalPadding,
      this.link = true,
      this.hideDivider = false,
      this.fontSizeBuilder,
      this.fontWeightBuilder,
      this.customView});

  @override
  KqPadTabBarPageViewState createState() => KqPadTabBarPageViewState();
}

class KqPadTabBarPageViewController {
  KqPadTabBarPageViewState? myState;

  bind(KqPadTabBarPageViewState state) {
    myState = state;
  }

  /// 跳转到指定页面
  jumpToPage(int page, {bool animate = false}) {
    myState?.jumpToPage(page, animate: animate);
  }

  void update() {
    myState?.update();
  }
}

class KqPadTabBarPageViewState extends State<KqPadTabBarPageView>
    with TickerProviderStateMixin {
  TabController? _tabController;

  int pageIndex = 0;

  update() {
    setState(() {});
  }

  @override
  void initState() {
    widget.controller?.bind(this);

    _initData();

    super.initState();
  }

  void _onPageChanged(int index) {
    widget.onPageChanged?.call(index, widget.tabs[index]);
  }

  @override
  void didUpdateWidget(covariant KqPadTabBarPageView oldWidget) {
    if (oldWidget.tabs.length != widget.tabs.length ||
        oldWidget.initialPageIndex != widget.initialPageIndex) {
      _initData();
    }
    super.didUpdateWidget(oldWidget);
  }

  @override
  void dispose() {
    _tabController?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    widget.controller?.bind(this);
    if (widget.indicatorType == PadIndicatorType.roundBg) {
      // 只有数字全部显示时，才调整角标可见性
      bool allShow = true;
      for (var element in widget.tabs) {
        if (element.hideNumber) {
          allShow = false;
        }
      }
      if (allShow) {
        if (_tabController != null) {
          _updateNumberVisible(_tabController!.index, false);
        }
      }
    }
    var pageView = KqPadTabBarView(
      controller: _tabController,
      onPageChanged: (value) {
        if (pageIndex != value) {
          pageIndex = value;
          _updateNumberVisible(value, true);
        }
      },
      autoHeight: widget.pageViewAutoHeight,
      physics: widget.pageScrollable
          ? const BouncingScrollPhysics()
          : const NeverScrollableScrollPhysics(),
      shouldIgnorePointerWhenScrolling: widget.shouldIgnorePointerWhenScrolling,
      link: widget.link,
      children: widget.pages,
    );
    return ClipRect(
      child: Column(
        mainAxisSize:
            widget.pageViewAutoHeight ? MainAxisSize.min : MainAxisSize.max,
        children: [
          KqPadTabBar(
              indicatorType: widget.indicatorType,
              indicatorSize: widget.indicatorSize,
              items: widget.tabs,
              textColorBuilder: widget.textColorBuilder,
              underlineColorBuilder: widget.underlineColorBuilder,
              dividerColor: widget.dividerColor,
              tabController: _tabController,
              tabBarHorizontalMargin: widget.tabBarHorizontalMargin,
              backgroundColor: widget.tabBarBackgroundColor,
              scrollable: widget.tabScrollable,
              customTabRightView: widget.customTabRightView,
              hideDivider: widget.hideDivider,
              fontSizeBuilder: widget.fontSizeBuilder,
              fontWeightBuilder: widget.fontWeightBuilder,
              indicatorHorizontalPadding: widget.indicatorHorizontalPadding),
          widget.customView ?? Container(),
          if (widget.customTabBottomView != null) widget.customTabBottomView!,
          widget.endDrawer == null
              ? (widget.pageViewAutoHeight
                  ? pageView
                  : Expanded(child: pageView))
              : (widget.pageViewAutoHeight
                  ? MediaQuery.removePadding(
                      context: context,
                      removeTop: true,
                      child: Scaffold(
                        key: widget.drawerGlobalKey,
                        endDrawer: widget.endDrawer,
                        backgroundColor: widget.pageBackgroundColor,
                        body: pageView,
                      ),
                    )
                  : Expanded(
                      child: MediaQuery.removePadding(
                      context: context,
                      removeTop: true,
                      child: Scaffold(
                        key: widget.drawerGlobalKey,
                        endDrawer: widget.endDrawer,
                        backgroundColor: widget.pageBackgroundColor,
                        body: pageView,
                      ),
                    )))
        ],
      ),
    );
  }

  //更新角标是否可见
  void _updateNumberVisible(int value, bool update) {
    if (widget.indicatorType == PadIndicatorType.roundBg) {
      if (update) {
        setState(() {
          for (var element in widget.tabs) {
            element.hideNumber = false;
          }
          widget.tabs[value].hideNumber = true;
        });
      } else {
        for (var element in widget.tabs) {
          element.hideNumber = false;
        }
        widget.tabs[value].hideNumber = true;
      }
    }
  }

  /// 跳转到指定页面
  void jumpToPage(int page, {bool animate = false}) {
    if (animate) {
      _tabController?.animateTo(page);
    } else {
      _tabController?.index = page;
    }
  }

  void _initData() {
    pageIndex = widget.initialPageIndex;
    _tabController?.dispose();
    _tabController = TabController(
        initialIndex: widget.initialPageIndex,
        length: widget.tabs.length,
        animationDuration: kqTabScrollDuration,
        vsync: this);
    _tabController?.addListener(() {
      if (!_tabController!.indexIsChanging) {
        _onPageChanged(_tabController!.index);
      }
    });
    if (widget.indicatorType == PadIndicatorType.roundBg) {
      for (var element in widget.tabs) {
        element.hideNumber = false;
      }
      widget.tabs[widget.initialPageIndex].hideNumber = true;
    }
  }
}

class KqPadTabBarView extends StatelessWidget {
  /// Creates a page view with one child per tab.
  ///
  /// The length of [children] must be the same as the [controller]'s length.
  const KqPadTabBarView(
      {super.key,
      required this.children,
      this.controller,
      this.physics,
      this.onPageChanged,
      this.autoHeight = false,
      this.dragStartBehavior = DragStartBehavior.start,
      this.viewportFraction = 1.0,
      this.clipBehavior = Clip.hardEdge,
      this.shouldIgnorePointerWhenScrolling = true,
      this.link = true});

  /// This widget's selection and animation state.
  ///
  /// If [TabController] is not provided, then the value of [DefaultTabController.of]
  /// will be used.
  final TabController? controller;

  /// One widget per tab.
  ///
  /// Its length must match the length of the [KqTabBar.tabs]
  /// list, as well as the [controller]'s [TabController.length].
  final List<Widget> children;

  /// How the page view should respond to user input.
  ///
  /// For example, determines how the page view continues to animate after the
  /// user stops dragging the page view.
  ///
  /// The physics are modified to snap to page boundaries using
  /// [PageScrollPhysics] prior to being used.
  ///
  /// Defaults to matching platform conventions.
  final ScrollPhysics? physics;

  final ValueChanged<int>? onPageChanged;

  /// {@macro flutter.widgets.scrollable.dragStartBehavior}
  final DragStartBehavior dragStartBehavior;

  /// {@macro flutter.widgets.pageview.viewportFraction}
  final double viewportFraction;

  /// {@macro flutter.material.Material.clipBehavior}
  ///
  /// Defaults to [Clip.hardEdge].
  final Clip clipBehavior;

  /// 是否根据子View高度自动调整高度
  final bool autoHeight;

  /// 当 Scrollable 滚动未停止的时候，是默认阻止其内容获得 hittest， 这就会导致在快速切换 tab 的时候， 给人一种不能马上操作内容的感觉
  /// 将 ShouldIgnorePointerWhenScrolling 设置成false，这样的话 Scrollable 在滚动中也不会阻止内容获得 hittest。
  final bool shouldIgnorePointerWhenScrolling;

  /// 是否关联父类滑动，此值为true时，当自身不可滑动时，会将滑动事件传递给父类
  final bool link;

  @override
  Widget build(BuildContext context) {
    return KqExtendedTabBarView(
      dragStartBehavior: dragStartBehavior,
      clipBehavior: clipBehavior,
      onPageChanged: onPageChanged,
      physics: physics,
      controller: controller,
      autoHeight: autoHeight,
      viewportFraction: viewportFraction,
      shouldIgnorePointerWhenScrolling: shouldIgnorePointerWhenScrolling,
      link: link,
      children: children,
    );
  }
}
